package org.myhibernate.core;

import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jdom.Element;
public class Mappings 
{
	private static Map<String,String> methodMap=new HashMap<String, String>();
	private static Map<String,Mapping> mappingMap=new HashMap<String, Mapping>();
	private static String charactor="utf-8";
	public static boolean sqlShow=true;
	public static String model=""; 
	public static String xmlConnfigPath="application.xml";
	public static String dbType="";
	static
	{
		initDefault();
		load();
	}
	public static void load()
	{
		XMLUtil xmlUtil=new XMLUtil();
		String xml="";
		try {
			InputStream is= Mappings.class.getClassLoader().getResourceAsStream(xmlConnfigPath);
			if (is==null) {
				System.out.println("Not found: "+xmlConnfigPath);
				return;
			}
			xml=xmlUtil.readFile(is, charactor);
		} catch (Exception e) {
			System.out.println("Exception for load : "+xmlConnfigPath);
			//e.printStackTrace();
			return;
		}
		//System.out.println("xml="+xml);
		List<Element> list=null;
		Element element=null;
		Element root=null;
		//get language
		try {
			root=xmlUtil.getXmlRoot(xml);
			//get sql show
			list=root.getChildren("sqlshow");
			if (list.size()>0)
			{
				element=list.get(0);
				sqlShow=Boolean.parseBoolean(element.getAttributeValue("value"));
			}
			list=root.getChildren("language");//xmlUtil.getXmlChildren(xml, "language");
			if (list.size()>0)
			{
				element=list.get(0);
				dbType=element.getAttributeValue("value")+"";
				if ("db2".equalsIgnoreCase(dbType)) {
					model=element.getAttributeValue("model");
				}
				LanguageHandle.setDB_TYPE(dbType.toLowerCase());
			}
			// cache
			//list=root.getChildren("cache");
			// get methods
			//list=xmlUtil.getXmlChildren(xml, "methods");
			list=root.getChildren("methods");
			if (list.size()>0)
			{
				element=list.get(0);
				list=element.getChildren("method");
				for (int i = 0; i < list.size(); i++)
				{
					Element methodElement=list.get(i);
					getMethodMap().put(methodElement.getAttributeValue("name"), methodElement.getAttributeValue("class"));
					//System.out.println(methodElement.getAttributeValue("name")+"="+ methodElement.getAttributeValue("class"));
				}
			}
			//get mapping s
			//list=xmlUtil.getXmlChildren(xml, "mapping");
			list=root.getChildren("mapping");
			//System.out.println("mapping.size="+list.size());
			for (int i = 0; i < list.size(); i++)
			{
				Element mappingElement=list.get(i);
				Mapping mapping=new Mapping();
				mapping.setName(mappingElement.getAttributeValue("name"));
				mapping.setTable(mappingElement.getAttributeValue("table"));
				
				Element idElement=mappingElement.getChild("id");
				String idFieldName=idElement.getAttributeValue("field");
				mapping.setId_Column(idFieldName);
				List<Element> properties=mappingElement.getChildren("property");
				Element propertyElement=null;
				for (int j = 0; j < properties.size(); j++) 
				{
					propertyElement=properties.get(j);
					mapping.getPropertyGetList().add(propertyElement.getAttributeValue("get"));
					mapping.getPropertySetList().add(propertyElement.getAttributeValue("set"));
					mapping.getPropertyColList().add(propertyElement.getAttributeValue("column"));
					mapping.getPropertyList().add(propertyElement.getAttributeValue("field"));
					if (idFieldName.equals(propertyElement.getAttributeValue("field"))) 
					{
						mapping.setId_Get(propertyElement.getAttributeValue("get"));
						mapping.setId_Set(propertyElement.getAttributeValue("set"));
						mapping.setId_Column(propertyElement.getAttributeValue("column"));
						mapping.setId_Field(propertyElement.getAttributeValue("field"));
					}
					mapping.getMethod_get_map().put(propertyElement.getAttributeValue("field"), propertyElement.getAttributeValue("get"));
					mapping.getMethod_set_map().put(propertyElement.getAttributeValue("field"), propertyElement.getAttributeValue("set"));
					mapping.getPropertyColMap().put(propertyElement.getAttributeValue("field"), propertyElement.getAttributeValue("column"));
				}
				mapping.initColumns();
				mapping.setTable(model+mapping.getTable());
				//System.out.println(mapping.getColumns());
				getMappingMap().put(mapping.getName(),mapping);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	private static void initDefault()
	{
		getMethodMap().put("add","org.myhibernate.core.method.AddMethod");
		getMethodMap().put("addbatch","org.myhibernate.core.method.AddBatchMethod");
		getMethodMap().put("delete","org.myhibernate.core.method.DeleteMethod");
		getMethodMap().put("deletes","org.myhibernate.core.method.DeletesMethod");
		getMethodMap().put("update","org.myhibernate.core.method.UpdateMethod");
		getMethodMap().put("updatefield","org.myhibernate.core.method.UpdateFieldMethod");
		getMethodMap().put("updatebatch","org.myhibernate.core.method.UpdateBatchMethod");
		getMethodMap().put("get","org.myhibernate.core.method.GetMethod");
		getMethodMap().put("getitem","org.myhibernate.core.method.GetItemMethod");
		getMethodMap().put("load","org.myhibernate.core.method.LoadMethod");
		getMethodMap().put("pagesizequery","org.myhibernate.core.method.PageSizeQuery");
		
	}
	public static Mapping loadClass(Class cls)
	{
		if (cls == null) {
			return null;
		}
		Mapping mapping=new Mapping();
		String simpleName=cls.getSimpleName();
		Field[] fields= cls.getDeclaredFields();
		
		mapping.setName(simpleName);
		mapping.setTable(simpleName.toUpperCase());
		
		mapping.setId_Column("id");
		mapping.setId_Get("getId");
		mapping.setId_Set("setId");
		mapping.setId_Column("ID");
		mapping.setId_Field("id");
		
		Field field=null;
		String fieldName="",get="",set="";
		for (int j = 0; j < fields.length; j++) 
		{
			field=fields[j];
			fieldName=field.getName();
			get="get"+(fieldName.charAt(0)+"").toUpperCase()+fieldName.substring(1);
			set="set"+(fieldName.charAt(0)+"").toUpperCase()+fieldName.substring(1);
			mapping.getPropertyGetList().add(get);
			mapping.getPropertySetList().add(set);
			mapping.getPropertyColList().add(fieldName.toUpperCase());
			mapping.getPropertyList().add(fieldName);
			mapping.getMethod_get_map().put(fieldName, get);
			mapping.getMethod_set_map().put(fieldName,set);
			mapping.getPropertyColMap().put(fieldName, fieldName.toUpperCase());
		}
		mapping.initColumns();
		mapping.setTable(model+mapping.getTable());
		getMappingMap().put(mapping.getName(),mapping);
		
		return mapping;
	}
	public static String getMethod(String name)
	{
		return methodMap.get(name);
	}
	public synchronized static Mapping getMapping(Class cls)
	{
		Mapping mapping=mappingMap.get(cls.getSimpleName());
		if (mapping==null) 
		{
			mapping=loadClass(cls);
		}
		return mapping;
	}
	public static Map<String, String> getMethodMap() {
		return methodMap;
	}
	public static Map<String, Mapping> getMappingMap() {
		return mappingMap;
	}

}
